/*
 * PhotonRTOS础光实时操作系统 -- 时间
 *
 * Copyright (C) 2022, 2023 国科础石(重庆)软件有限公司
 *
 * 作者: Baoyou Xie <xiebaoyou@kernelsoft.com>
 *
 * License terms: GNU General Public License (GPL) version 3
 *
 */

#ifndef _OS_TIME_H
#define _OS_TIME_H

#include <photon/types.h>

#define HZ CONFIG_HZ
extern uint64_t jiffies_64;
extern uint32_t jiffies;

/**
 * jiffies比较，可以处理32位计数溢出。
 */
#define time_after(a, b)		\
	(typecheck(uintptr_t, a) && \
	 typecheck(uintptr_t, b) && \
	 ((intptr_t)(b) - (intptr_t)(a) < 0))
#define time_before(a, b)	time_after(b, a)
#define time_after_eq(a, b)	\
	(typecheck(uintptr_t, a) && \
	 typecheck(uintptr_t, b) && \
	 ((intptr_t)(a) - (intptr_t)(b) >= 0))
#define time_before_eq(a, b)	time_after_eq(b, a)

uint64_t get_jiffies_64(void);
void add_jiffies_64(uintptr_t ticks);

#define NSEC_PER_USEC (1000L)
#define NSEC_PER_SEC (1000000000L)
#define TICK_NSEC (NSEC_PER_SEC / HZ)

static inline uint32_t jiffies_to_msecs(const uintptr_t j)
{
#if HZ <= 1000 && !(1000 % HZ)
	return (1000 / HZ) * j;
#elif HZ > 1000 && !(HZ % 1000)
	return (j + (HZ / 1000) - 1)/(HZ / 1000);
#else
	return (j * 1000) / HZ;
#endif
}

static inline uintptr_t msecs_to_jiffies(const uint32_t m)
{
#if HZ <= 1000 && !(1000 % HZ)
	return (m + (1000 / HZ) - 1) / (1000 / HZ);
#elif HZ > 1000 && !(HZ % 1000)
	return m * (HZ / 1000);
#else
	return (m * HZ + 999) / 1000;
#endif
}

uintptr_t cycles_to_usecs(const uintptr_t cycles);

void check_timer_validity(void);

#endif /* _OS_TIME_H */
